﻿using System.Collections.Generic;
using System.Linq;

namespace UniSender
{
    using Expando = Dictionary<string, object>;

    partial class Client
    {
        /// <summary>
        /// Получить списки рассылки с их кодами
        /// </summary>
        /// <returns>Массив списков рассылки</returns>
        public virtual MailList[] GetLists()
        {
            return Apply<Native.MailList[]>("getLists")
                .IfNotNull(result => result.Select(r => new MailList(r)).ToArray());
        }


        /// <summary>
        /// Создать новый список рассылки
        /// </summary>
        /// <param name="title">Название списка</param>
        /// <returns>Созданный список рассылки</returns>
        public virtual MailList CreateList(string title)
        {
            return Apply<Native.MailList>("createList", new Expando()
                {
                    { "title", title }
                })
                .IfNotNull(list => new MailList(list.id, title));
        }

        /// <summary>
        /// Создать новый список рассылки
        /// </summary>
        /// <param name="title">Название списка</param>
        /// <param name="beforeSubscribeUrl">URL для редиректа на страницу "перед подпиской"</param>
        /// <param name="afterSubscribeUrl">URL для редиректа на страницу "после подписки"</param>
        /// <returns>Созданный список рассылки</returns>
        public virtual MailList CreateList(string title, string beforeSubscribeUrl, string afterSubscribeUrl)
        {
            return Apply<Native.MailList>("createList", new Expando()
                {
                    { "title", title },
                    { "before_subscribe_url", beforeSubscribeUrl },
                    { "after_subscribe_url", afterSubscribeUrl }
                })
                .IfNotNull(list => new MailList(list.id, title));
        }

        
        /// <summary>
        /// Изменить свойства списка рассылки
        /// </summary>
        /// <param name="listId">Код списка</param>
        /// <param name="title">Название списка</param>
        /// <param name="beforeSubscribeUrl">URL для редиректа на страницу "перед подпиской"</param>
        /// <param name="afterSubscribeUrl">URL для редиректа на страницу "после подписки"</param>
        public virtual void UpdateList(long listId, string title, string beforeSubscribeUrl, string afterSubscribeUrl)
        {
            Apply("updateList", new Expando()
                {
                    { "list_id", listId },
                    { "title", title },
                    { "before_subscribe_url", beforeSubscribeUrl },
                    { "after_subscribe_url", afterSubscribeUrl }
                });
        }

        /// <summary>
        /// Изменить свойства списка рассылки
        /// </summary>
        /// <param name="listId">Код списка</param>
        /// <param name="title">Название списка</param>
        public virtual void UpdateList(long listId, string title)
        {
            Apply("updateList", new Expando()
                {
                    { "list_id", listId },
                    { "title", title }
                });
        }

        /// <summary>
        /// Изменить свойства списка рассылки
        /// </summary>
        /// <param name="list">Список рассылки</param>
        public virtual void UpdateList(MailList list)
        {
            Apply("updateList", new Expando()
                {
                    { "list_id", list.Id },
                    { "title", list.Title }
                });
        }


        /// <summary>
        /// Удалить список рассылки
        /// </summary>
        /// <param name="listId">Код списка</param>
        public virtual void DeleteList(long listId)
        {
            Apply("deleteList", new Expando()
                {
                    { "list_id", listId }
                });
        }


        /// <summary>
        /// Подписать адресата на один или несколько списков рассылки
        /// </summary>
        /// <param name="args">Параметры подписки</param>
        /// <returns>Уникальный код подписчика</returns>
        public virtual long? Subscribe(SubscribeConfig args)
        {
            return Apply<Native.SubscribeResult>("subscribe", args.Serialize())
                .IfNotNull(result => result.person_id);
        }


        /// <summary>
        /// Отписать адресата от рассылки
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        /// <param name="listIds">Коды списков, от которых мы отписываем подписчика, если не указаны, то отписываем от всех списков</param>
        public virtual void Unsubscribe(ContactType type, string contact, long[] listIds)
        {
            Apply("unsubscribe", new Expando()
                {
                    { "contact_type", type.Stringify() },
                    { "contact", contact },
                    { "list_ids", listIds }
                });
        }

        /// <summary>
        /// Отписать адресата от рассылки
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        /// <param name="listIds">Код списка, от которого мы отписываем подписчика</param>
        public void Unsubscribe(ContactType type, string contact, long listId)
        {
            Unsubscribe(type, contact, new long[] { listId });
        }

        /// <summary>
        /// Отписать адресата от всех рассылок
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        public void Unsubscribe(ContactType type, string contact)
        {
            Unsubscribe(type, contact, null);
        }


        /// <summary>
        /// Исключить адресата из списков рассылки
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        /// <param name="listIds">Коды списков, от которых мы отписываем подписчика, если не указаны, то отписываем от всех списков</param>
        public virtual void Exclude(ContactType type, string contact, long[] listIds)
        {
            Apply("exclude", new Expando()
                {
                    { "contact_type", type.Stringify() },
                    { "contact", contact },
                    { "list_ids", listIds }
                });
        }

        /// <summary>
        /// Исключить адресата из списков рассылки
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        /// <param name="listId">Код списка, от которого мы отписываем подписчика</param>
        public void Exclude(ContactType type, string contact, long listId)
        {
            Exclude(type, contact, new long[] { listId });
        }

        /// <summary>
        /// Исключить адресата из всех списков рассылки
        /// </summary>
        /// <param name="type">Тип отписываемого контакта</param>
        /// <param name="contact">E-mail или телефон, который надо отписать от рассылок</param>
        public void Exclude(ContactType type, string contact)
        {
            Exclude(type, contact, null);
        }


        /// <summary>
        /// Массовый импорт и синхронизация контактов
        /// </summary>
        /// <param name="args">Данные и параметры импорта</param>
        /// <returns>Результат импорта</returns>
        public virtual ImportResult ImportContacts(ImportConfig args)
        {
            return Apply<Native.ImportResult>("importContacts", args.Serialize())
                .IfNotNull(result => new ImportResult(result));
        }

        /// <summary>
        /// Экспорт данных контактов
        /// </summary>
        /// <param name="args">Параметры экспорта</param>
        /// <returns>Результат экспорта</returns>
        public virtual Subscriber[] ExportContacts(ExportConfig args)
        {
            return Apply<Native.ExportResult>("exportContacts", args.Serialize())
                .IfNotNull(result => Parser.ParseExport(result));
        }
    }
}
